const winston = require('winston')
require('winston-daily-rotate-file')

var helper = module.exports = {}

const env = process.env.NODE_ENV
const uuidv4 = require('uuid/v4')
const config = require('config')

// 错误信息日志
const ERROR_LOG_NAME = './logs/error.log'

// 所有运行日志
const APP_LOG_NAME = './logs/app-%DATE%.log'
// 保存天数
const SAVE_DAYS = config.log.saveDays || '5d'
// 文件大小分割
const MAX_SIZE = config.log.maxSize || '100m'

// 日志级别
const levels = {
  error: 0,
  warn: 1,
  info: 2,
  verbose: 3,
  debug: 4,
  silly: 5
}

// 格式化输出内容
const formatter = winston.format.combine(
  winston.format.json(),
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  winston.format.printf(info => {
    // 输出格式
    if (info.level === 'error') {
      const logData = info.message.map((e) => {
        console.error(e)
        if (e && e.message && e.stack) {
          e = Object.assign({ message: e.message, stack: e.stack }, e)
        }
        return e
      })
      const errWrapper = { time: info.timestamp, pid: process.pid, message: info.message, error: logData }
      return JSON.stringify(errWrapper)
    }
    const showInfo = { time: info.timestamp, pid: process.pid, level: info.level, message: info.message }
    return JSON.stringify(showInfo)
  })
)

const logger = winston.createLogger({
  levels: levels,
  format: formatter,
  transports: [
    // 'error'级别的日志处理
    new winston.transports.File({
      level: 'error',
      filename: ERROR_LOG_NAME
    }),
    // '所有的日志处理, maxFiles是回滚时间，超时会删除旧文件，如果不设置，则不会删除'
    // TODO 分别几区处理日志，分多app_name日志处理
    new (winston.transports.DailyRotateFile)({
      filename: APP_LOG_NAME,
      zippedArchive: true,
      maxFiles: SAVE_DAYS,
      maxSize: MAX_SIZE
    }),
    // 控制台输出
    new winston.transports.Console({})
  ]
})

// logger.add(winston.transports.Logstash, {
//   port: 8888,
//   node_name: 'my node name',
//   host: '127.0.0.1'
// })

helper.debug = function (...msg) {
  if (msg == null) {
    msg = ''
  }
  logger.debug(...msg)
}

helper.info = function (...msg) {
  if (msg == null) {
    msg = ''
  }
  logger.info(...msg)
}

helper.warn = function (...msg) {
  if (msg == null) {
    msg = ''
  }
  logger.warn(msg)
}

helper.error = function (...msg) {
  if (msg == null) {
    msg = ''
  }
  logger.error(msg)
}

helper.resLogger = function (ctx, resTime) {
  if (ctx) {
    helper.info(formatRes(ctx, resTime))
  }
}

helper.accessLogger = function (ctx, startTime) {
  if (ctx) {
    ctx.trackingId = uuidv4()
    helper.info(formatAccess(ctx, startTime))
  }
}

helper.handleLogger = function (ctx, className, funcName) {
  if (env !== 'production' && ctx) {
    const status = 'Handle'
    let trackingId = ctx.trackingId
    helper.info({ status, trackingId, className, funcName })
  }
}

helper.errHandleLogger = function (ctx, className, funcName, err) {
  if (ctx) {
    const status = 'Error'
    let trackingId = ctx.trackingId
    helper.error(status, trackingId, className, funcName, err)
  }
}

let formatAccess = (ctx, timestamp) => {
  let status = 'Access'
  let trackingId = ctx.trackingId
  let method = ctx.method
  let url = decodeURIComponent(ctx.url)
  let ip = ctx.ip
  let requestBody = JSON.stringify(ctx.request.body)
  return { status, trackingId, method, url, ip, requestBody, timestamp }
}

let formatRes = (ctx, duration) => {
  let status = 'Response'
  let trackingId = ctx.trackingId
  let method = ctx.method
  let url = decodeURIComponent(ctx.url)
  let ip = ctx.ip
  let requestId = ctx.headers['gm-request-id']
  let requestBody = ctx.request.body
  let responseBody = ctx.response.body
  if (env !== 'production') {
    requestBody = JSON.stringify(ctx.request.body)
    responseBody = JSON.stringify(ctx.response.body)
  }
  return { status, trackingId, method, url, ip, requestBody, duration, responseBody, requestId }
}

// 配合Koa用的方法
helper.init = function (app) {
  app.use(async (ctx, next) => {
    const startTime = Date.now()
    helper.accessLogger(ctx, startTime)
    await next()
    const duration = Date.now() - startTime
    helper.resLogger(ctx, duration)
  })
}

// module.exports = logger
